/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		polygon_interface.hpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-01-17 16:54
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-04-03 17:30
*
*   Description:
*
=============================================================================*/
#ifndef I_POLYGON_H
#define I_POLYGON_H

#include "shape_interface.hpp"

namespace geoxfem {
namespace geometry {

template <typename DimensionType, typename degree>
struct PolygonInterface : ShapeInterface<DimensionType, degree> {

  using type       = boost::geometry::ring_tag;
  using Shape      = ShapeInterface<DimensionType, degree>;
  using point_type = typename traits::point_type<DimensionType>::type;
  using Gauss      = model::GaussPoint<DimensionType>;

  /*constructors and destructor{{{*/

  /**
   * @brief constructor.
   *
   * @param _listPoint
   */
  PolygonInterface(const std::vector<point_type>& _listPoint)
      : Shape{_listPoint} {
    std::sort(this->begin(), this->end(),
              algorithm::clock_wise<point_type>(*this));

    boost::geometry::correct(*this);
  }
  PolygonInterface()          = default;
  virtual ~PolygonInterface() = default;
  /*}}}*/
  /*misc{{{*/

  PolygonInterface<DimensionType, degree>& toPolygon() final override {
    return *this;
  }
  const PolygonInterface<DimensionType, degree>&
  toPolygon() const final override {
    return *this;
  }
  /*}}}*/
  /*override functions{{{*/

  /**
   * @brief get Topology Dimension of current shape
   *
   * @return
   */
  size_t getTopologyDimension() const final override {
    return 2;
  }
  /**
   * @brief buildStdGaussPoints
   *
   * @param
   */
  virtual void getStdGaussPoints(std::vector<Gauss>&) override {
    GEOXFEM_NOT_IMPLEMENTED();
  }
  /*}}}*/
  /*topology connectivity{{{*/

  std::vector<std::unique_ptr<Shape>> createFacet() const final override {
    const size_t d  = degree::value;
    GEOXFEM_ASSERT((this->size() - 1) % d == 0);
    std::vector<std::unique_ptr<Shape>> v;
    for(auto it = this->begin(); it != this->end() - 1; it = it + d) {
      std::vector<point_type> plist{it, it + (d + 1)};
      v.emplace_back(Shape::getFactory().create("Segment", plist));
    }
    return v;
  }
  /*}}}*/
};

};  // namespace geometry
};  // namespace geoxfem

GEOXFEM_REGISTER_TEMPLATIZED(geoxfem::geometry::PolygonInterface);

#endif  // I_POLYGON_H
